/*================================================================
*   Copyright (C) 2014 All rights reserved.
*   
*   文件名称：Log.cpp
*   创 建 者：Zhang Yuanhao
*   邮    箱：bluefoxah@gmail.com
*   创建日期：2014年09月10日
*   描    述：
*
#include "Log.h"
 ================================================================*/
#include <sys/stat.h>
#include <time.h>
#include <assert.h>
#include "Log.h"
#include "util.h"
#include "ImPduClient.h"

CLog* CLog::m_pInstance = NULL;

char g_szLog[10240];
char g_szContent[10240];
char g_szTime[32];
CLock   *g_lock = NULL;
const char* g_ClientMap[9] =
{
    "U",        //  UNKNOWN
    "W",        //  Windows
    "M",        //  MAC
    "F",        //  Flash
    "A",        //  Android
    "I",        //  IOS
    "WP",       //  WinPhone
    "H",        //  HTTP
    "P",        //  PUSH
};

CLog::~CLog()
{
    if(m_pFile)
    {
        
        fclose(m_pFile);
        m_pFile = NULL;
    }
}

CLog* CLog::getInstance()
{
    if(m_pInstance == NULL)
    {
        m_pInstance = new CLog();
    }
    return m_pInstance;
}

bool CLog::Init(const char* pPath)
{
    CAutoLock lock(g_lock);
    
    if(m_bInited)
        return true;
    
    m_pFile = NULL;
    m_pFileLocal = NULL;
    m_nFileIndex = 0;
    
    if(pPath == NULL)
    {
        snprintf(m_szPath, sizeof(m_szPath), "%s", DEFAULT_LOG_PATH);
    }
    else
    {
        snprintf(m_szPath, sizeof(m_szPath), "%s", pPath);
    }
    struct stat filestat;
    if(stat(m_szPath, &filestat) != 0)
    {
#ifdef _WIN32
		int status = _mkdir(m_szPath);
#else
		int status = mkdir(m_szPath, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
#endif
        assert(0 == status);
    }
    
    if(!InitLog()) {
        return false;
    }
    
    m_bInited = true;
    m_lastTime = 0;
    return true;
}

bool CLog::InitLog()
{
    time_t curTime;
    time(&curTime);
    tm* tm1 = localtime(&curTime);
    int nYear, nYday, nMon, nDay;
    nYear = tm1->tm_year;
    nYday = tm1->tm_yday;
    nMon = tm1->tm_mon;
    nDay = tm1->tm_mday;
    
    
    char date_dir[64] = {0};
    snprintf(date_dir, sizeof(date_dir), "%s/%04d-%02d-%02d",  m_szPath, nYear+1900, nMon+ 1, nDay);
    
    struct stat filestat;
    if(stat(date_dir, &filestat) != 0)
    {
#ifdef _WIN32
		int status = _mkdir(date_dir);
#else
        int status = mkdir(date_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
#endif
        assert(0 == status);
    }
    
    char file_index_path[64] = {0};
    snprintf(file_index_path, sizeof(file_index_path), "%s/index.txt",  date_dir);
    if(stat(file_index_path, &filestat) != 0)
    {
        m_nFileIndex = 0;
        FILE* pFile = fopen(file_index_path, "w");
        if (!pFile) {
            return false;
        }
        
        fprintf(pFile, "%05d", m_nFileIndex);
        fclose(pFile);
    }
    else
    {
        FILE* pFile = fopen(file_index_path, "r+w");
        if(!pFile) {
            return false;
        }
        
        if(1 != fscanf(pFile, "%05d", &m_nFileIndex))
        {//文件创建，内容不对或为空
            m_nFileIndex = 0;
        }
        fseek(pFile, 0, SEEK_SET);
        fprintf(pFile, "%05d", m_nFileIndex);
        fflush(pFile);
        fclose(pFile);
    }
    
    return true;
}
#ifdef _WIN32
bool CLog::isSameDay(const time_t t1, const time_t t2)
{
	tm temptm1 = *localtime(&t1);
	SYSTEMTIME st1 = {1900 + temptm1.tm_year, 
		1 + temptm1.tm_mon, 
		temptm1.tm_wday, 
		temptm1.tm_mday, 
		temptm1.tm_hour, 
		temptm1.tm_min, 
		temptm1.tm_sec, 
		0};
	tm temptm2 = *localtime(&t2);
	SYSTEMTIME st2 = {1900 + temptm2.tm_year, 
		1 + temptm2.tm_mon, 
		temptm2.tm_wday, 
		temptm2.tm_mday, 
		temptm2.tm_hour, 
		temptm2.tm_min, 
		temptm2.tm_sec, 
		0};
	return (st1.wYear == st2.wYear && st1.wMonth == st2.wMonth && st1.wDay == st2.wDay);
}
#else
bool CLog::isSameDay(const time_t t1, const time_t t2)
{
    tm tm1;
	tm tm2;
	if(localtime_r(&t1, &tm1) == NULL)
    {
        return false;
    }
	if(localtime_r(&t2, &tm2) == NULL)
    {
        return false;
    }
	if ( tm1.tm_year == tm2.tm_year
		&& tm1.tm_yday == tm2.tm_yday)
	{
		return true;
	}
	return false;
}
#endif

void CLog::writeLog(const char *content)
{
    time_t curTime;
    time(&curTime);
    tm* tm1 = localtime(&curTime);
    int nYear, nYday, nMon, nDay;
    nYear = tm1->tm_year;
    nYday = tm1->tm_yday;
    nMon = tm1->tm_mon;
    nDay = tm1->tm_mday;
    
    char date_dir[64] = {0};
    snprintf(date_dir, sizeof(date_dir), "%s/%04d-%02d-%02d",  m_szPath, nYear+1900, nMon+ 1, nDay);
    
    struct stat filestat;
    if(stat(date_dir, &filestat) != 0)
    {
#ifdef _WIN32 
		int status = _mkdir(date_dir);
#else
		int status = mkdir(date_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
#endif
        assert(0 == status);
    }
    
    char file_index_path[64] = {0};
    snprintf(file_index_path, sizeof(file_index_path), "%s/index.txt",  date_dir);
    if(stat(file_index_path, &filestat) != 0)
    {
        m_nFileIndex = 0;
        FILE* pFile = fopen(file_index_path, "w");
        if(!pFile)
            return;
        
        fprintf(pFile, "%05d", m_nFileIndex);
        fclose(pFile);
    }
    
    char szLogName[64];
    snprintf(szLogName, sizeof(szLogName), "%s/%05u.log",  date_dir, m_nFileIndex);
    if(stat(szLogName, &filestat) != 0)
    {//该写的文件不存在
        if(m_pFileLocal != NULL)
        {
            fflush(m_pFileLocal);
            fclose(m_pFileLocal);
            m_pFileLocal = NULL;
        }
        
        m_pFileLocal = fopen(szLogName, "a+");
    }
    else
    {
        if(m_pFileLocal == NULL)
        {
            m_pFileLocal = fopen(szLogName, "a+");
        }
    }
    
    if(m_pFileLocal != NULL)
    {
        if(content[strlen(content) - 1] == '\n')
        {
            fprintf(m_pFileLocal, "%s", content);
        }
        else
        {
            fprintf(m_pFileLocal, "%s\n", content);
        }
        fflush(m_pFileLocal);
        
        if (ftell(m_pFileLocal) > MAX_LOG_FILE_SIZE)
        {
            FILE* pFile = fopen(file_index_path, "r+w");
            if(!pFile)
                return;
            
            fprintf(pFile, "%05d", ++m_nFileIndex);
            fflush(pFile);
            fclose(pFile);
            
            fclose(m_pFileLocal);
            m_pFileLocal = NULL;
        }
    }
}

void sysLog(const char* fmt, ...)
{
    CAutoLock lock(g_lock);
    CLog* logger = CLog::getInstance();
#ifdef _WIN32
	SYSTEMTIME systemTime;
	GetLocalTime(&systemTime);
	snprintf(g_szTime, sizeof(g_szTime), "%04d-%02d-%02d\t%02d:%02d:%02d.%03d",systemTime.wYear, systemTime.wMonth, systemTime.wDay, 
		systemTime.wHour, systemTime.wMinute, systemTime.wSecond, systemTime.wMilliseconds);
#else 
	struct timeval tval;
	struct tm* tmNow;
	time_t currTime;
	time(&currTime);
	tmNow = localtime(&currTime);
	gettimeofday(&tval, NULL);
	snprintf(g_szTime, sizeof(g_szTime), "%04d-%02d-%02d\t%02d:%02d:%02d.%03d",tmNow->tm_year + 1900, tmNow->tm_mon + 1, tmNow->tm_mday, tmNow->tm_hour, tmNow->tm_min, tmNow->tm_sec, (int)tval.tv_usec / 1000);

#endif
   
    va_list ap;
    va_start(ap, fmt);
    vsnprintf(g_szContent, sizeof(g_szContent), fmt, ap);
    va_end(ap);
    
    snprintf(g_szLog, sizeof(g_szLog),  "%s\t%s", g_szTime, g_szContent);
    logger->writeLog(g_szLog);

}

void init_log(bool bUseLock)
{
    CLog* logger = CLog::getInstance();
    if(bUseLock)
        g_lock = new CLock;
    if(!logger->Init(DEFAULT_LOG_PATH)) {
        fprintf(stderr, "init_log failed\n");
        exit(0);
    }
}


















